﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using WJ.Infrastructure.Extension;

namespace WJ.Infrastructure.Web
{
    public static class WebResponse
    {
        #region 写cookie值
        public static void SetCookie(string name, string valu)
        {
            SetCookie(name, valu, null, null);
        }

        public static void SetCookie(string name, string valu, string domain)
        {
            SetCookie(name, valu, domain, null);
        }

        public static void SetCookie(string name, string valu, DateTime expires)
        {
            SetCookie(name, valu, null, expires);
        }

        public static void SetCookie(string name, string valu, string domain, DateTime? expires)
        {
            HttpCookie cookie = new HttpCookie(name, HttpUtility.UrlEncode(valu, Encoding.UTF8));
            if (expires != null)
            {
                cookie.Expires = (DateTime)expires;
            }

            if (!string.IsNullOrEmpty(domain)) cookie.Domain = domain;
            cookie.HttpOnly = true;

            HttpContext context = HttpContext.Current;
            context.Response.Cookies.Add(cookie);
        }

        public static void RemoveCookie(string name)
        {
            SetCookie(name, "", "", DateTime.Now.AddDays(-1));
        }

        /// <summary>
        /// 清除当前用户所有cookie
        /// </summary>
        public static void RemoveAllCookies()
        {
            HttpContext context = HttpContext.Current;
            foreach (string cookieKey in context.Request.Cookies.AllKeys)
            {
                context.Response.Cookies[cookieKey].Expires = DateTime.Now.AddDays(-1);
            }
        }
        #endregion

        #region 下载文件

        #region 以指定的ContentType输出指定文件文件
        /// <summary>
        /// 以指定的ContentType输出指定文件文件
        /// </summary>
        /// <param name="filepath">文件路径</param>
        /// <param name="filename">输出的文件名</param>
        /// <param name="filetype">将文件输出时设置的ContentType</param>
        public static void ResponseFile(string filepath, string filename, string filetype)
        {
            Stream iStream = null;

            // 缓冲区为10k
            byte[] buffer = new Byte[10000];

            // 文件长度
            int length;

            // 需要读的数据长度
            long dataToRead;

            try
            {
                // 打开文件
                iStream = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);


                // 需要读的数据长度
                dataToRead = iStream.Length;

                HttpContext.Current.Response.ContentType = filetype;
                HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + filename.Trim().UrlEncode().Replace("+", " "));

                while (dataToRead > 0)
                {
                    // 检查客户端是否还处于连接状态
                    if (HttpContext.Current.Response.IsClientConnected)
                    {
                        length = iStream.Read(buffer, 0, 10000);
                        HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
                        HttpContext.Current.Response.Flush();
                        buffer = new Byte[10000];
                        dataToRead = dataToRead - length;
                    }
                    else
                    {
                        // 如果不再连接则跳出死循环
                        dataToRead = -1;
                    }
                }
            }

            finally
            {
                if (iStream != null)
                {
                    // 关闭文件
                    iStream.Close();
                    iStream.Dispose();
                }
            }
            HttpContext.Current.Response.End();
        }
        #endregion

        #region 使用微软提供的TransmifFile下载文件
        /// <summary>
        /// 使用微软提供的TransmifFile下载文件 
        /// </summary>
        /// <param name="path">相对路径</param>
        public static void TransmitFile(string filePath)
        {
            try
            {
                filePath = filePath.GetMapPath();
                if (File.Exists(filePath))
                {
                    FileInfo info = new FileInfo(filePath);
                    long fileSize = info.Length;
                    HttpContext.Current.Response.Clear();
                    HttpContext.Current.Response.ContentType = "application/x-zip-compressed";
                    HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + info.FullName.UrlEncode());
                    //不指明Content-Length用Flush的话不会显示下载进度   
                    HttpContext.Current.Response.AddHeader("Content-Length", fileSize.ToString());
                    HttpContext.Current.Response.TransmitFile(filePath, 0, fileSize);
                    HttpContext.Current.Response.Flush();
                }
            }
            catch
            { }
            finally
            {
                HttpContext.Current.Response.Close();
            }

        }
        #endregion

        #region  使用WriteFile下载文件
        /// <summary>
        /// 使用WriteFile下载文件  
        /// </summary>
        /// <param name="filePath">相对路径</param>
        public static void WriteFile(string filePath)
        {

            try
            {
                filePath = filePath.GetMapPath();
                if (File.Exists(filePath))
                {
                    FileInfo info = new FileInfo(filePath);
                    long fileSize = info.Length;
                    HttpContext.Current.Response.Clear();
                    HttpContext.Current.Response.ContentType = "application/octet-stream";
                    HttpContext.Current.Response.AddHeader("Content-Disposition", "attachement;filename=" + info.FullName.UrlEncode());
                    //指定文件大小   
                    HttpContext.Current.Response.AddHeader("Content-Length", fileSize.ToString());
                    HttpContext.Current.Response.WriteFile(filePath, 0, fileSize);
                    HttpContext.Current.Response.Flush();
                }
            }
            catch
            { }
            finally
            {
                HttpContext.Current.Response.Close();
            }
        }
        #endregion

        #region 使用OutputStream.Write分块下载文件
        /// <summary>
        /// 使用OutputStream.Write分块下载文件  
        /// </summary>
        /// <param name="filePath"></param>
        public static void WriteFileBlock(string filePath)
        {
            filePath = filePath.GetMapPath();
            if (!File.Exists(filePath))
            {
                return;
            }
            FileInfo info = new FileInfo(filePath);
            //指定块大小   
            long chunkSize = 4096;
            //建立一个4K的缓冲区   
            byte[] buffer = new byte[chunkSize];
            //已读的字节数   
            long dataToRead = 0;
            FileStream stream = null;
            try
            {
                //打开文件   
                stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                dataToRead = stream.Length;

                //添加Http头   
                HttpContext.Current.Response.ContentType = "application/octet-stream";
                HttpContext.Current.Response.AddHeader("Content-Disposition", "attachement;filename=" + info.FullName.UrlEncode());
                HttpContext.Current.Response.AddHeader("Content-Length", dataToRead.ToString());

                while (dataToRead > 0)
                {
                    if (HttpContext.Current.Response.IsClientConnected)
                    {
                        int length = stream.Read(buffer, 0, Convert.ToInt32(chunkSize));
                        HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
                        HttpContext.Current.Response.Flush();
                        HttpContext.Current.Response.Clear();
                        dataToRead -= length;
                    }
                    else
                    {
                        //防止client失去连接   
                        dataToRead = -1;
                    }
                }
            }
            catch (Exception ex)
            {
                HttpContext.Current.Response.Write("Error:" + ex.Message);
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                    stream.Dispose();
                }
                HttpContext.Current.Response.Close();
            }

        }
        #endregion

        #endregion
    }
}
